package refect;

import org.junit.Test;
import org.omg.PortableInterceptor.INACTIVE;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestRefection {

    @Test
    public void test1() throws ClassNotFoundException {
        // 获取反射class对象三种方式
        Class<?> c1 = Class.forName("refect.Student");
        // 第二种
        Class c2 = Student.class;
        // 第三中
        Student s = new Student();
        Class c3 = s.getClass();

        System.out.println(c1);
        System.out.println(c1==c2);
        System.out.println(c1==c3);
    }


    @Test
    public void test2() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//    Class类中用于获取构造方法的方法
//    Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组
//    Constructor<?>[] getDeclaredConstructors():返回所有构造方法对象的数组
//    Constructor<T> getConstructor(Class<?>...parameterTypes):返回单个公共构造方法对象
//    Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes):返回单个构造方法对象Constructor类中用于创建对象的方法

//    T newlnstance(Object...initargs):根据指定的构造方法创建对象
//    setAccessible(boolean flag):设置为true,表示取消访问检查
        Class c1 = Class.forName("refect.Student");
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
//            System.out.println(constructor);
//            public refect.Student(java.lang.String,int)
//            public refect.Student()
        }
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
//            System.out.println(declaredConstructor);
//            private refect.Student(int,java.lang.String)
//            protected refect.Student(java.lang.String)
//            public refect.Student(int)
//            public refect.Student()
        }

        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class);
        System.out.println(declaredConstructor); // private refect.Student(java.lang.String,int)
        declaredConstructor.setAccessible(true); // 取消访问检查
        Student stu = (Student) declaredConstructor.newInstance("张三", 18);
        System.out.println(stu); // Student{name='张三', age=18}
    }
    @Test
    public void test3() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//        Class类中用于获取成员变量的方法
//        Field getFields():返回所有公共成员变量对象的数组
//        Field[] getDeclaredFields():返回所有成员变量对象的数组
//        Field getField(String name):返回单个公共成员变量对象
//        Field getDeclaredField(String name):返回单个成员变量对象Field类中用于创建对象的方法
//        void set(Object obj, Object value):赋值
//        Object get(Object obj)获取值。
        Class c1 = Class.forName("refect.Student");
        Field name = c1.getDeclaredField("name");
        System.out.println(name); // private java.lang.String refect.Student.name
        // 获取成员变量的名字
        String n = name.getName();
        System.out.println(n); // name
        // 获取成员变量的数据类型
        Class<?> type = name.getType();
        System.out.println(type);
        // 获取成员变量记录的值
        Student student = new Student("zhagnsan",23,"男");
        name.setAccessible(true);
        String value = (String) name.get(student);
        System.out.println(value);  // zhagnsan
        // 修改对象里面记录的值
        name.set(student,"lisi");
        System.out.println(student);
    }
    @Test
    public void test4() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//        Class类中用于获取成员方法的方法
//        Method[] getMethods():返回所有公共成员方法对象的数组，包括继承的
//        Method[] getDeclaredMethods():返回所有成员方法对象的数组，不包括继承的
//        Method getMethod(String name, Class... parameterTypes):返回单个公共成员方法对象
//        Method getDeclaredMethod(String name, Class... parameterTypes):返回单个成员方法对象Method类中用于创建对象的方法
//        Object invoke(Object ob), Object...args):运行方法
//    参数一：用obj对象调用该方法
//    参数二：调用方法的传递的参数（如果没有就不写）
//        返回值：方法的返回值（如果没有就不写）
        Class c1 = Class.forName("refect.Student");
        Method m = c1.getDeclaredMethod("eat", String.class);
        System.out.println(m);

        // 获取方法名字
        String name = m.getName();
        System.out.println(name);

        Student s = new Student();
        m.setAccessible(true);
        String hahaha = (String) m.invoke(s, "hahaha");
        System.out.println(hahaha);
    }

    @Test
    public void test5() throws IllegalAccessException, IOException {
        Person p = new Person("小A",23,"女",170,"睡觉");
        Teacher t = new Teacher("波妞",20000);

        BufferedWriter bw = new BufferedWriter(new FileWriter("H:\\springstudy\\BuildObject\\src\\main\\java\\a.txt"));
        // 获取字节码对
        Class c1 = p.getClass();
        Field[] fields = c1.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            // 获取变量名
            String name = field.getName();
            // 获取成员变量的值
            Object o = field.get(p);
            System.out.println(name+"="+o);
            bw.write(name+"="+o);
            bw.newLine();
        }
        bw.close();
    }

}
